home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
001
/
pibt40s1.arc
/
INT24.MOD
< prev
next >
Wrap
Text File
|
1986-03-01
|
10KB
|
214 lines
{ Version 2.0, 1/28/86
For MS-DOS version 2.0 or greater, Turbo Pascal 1.0 or greater.
Thanks to Marshall Brain for the original idea for these routines.
Thanks to John Cooper for pointing out a small flaw in the code.
These routines provide a method for Turbo Pascal programs to trap MS-DOS
interrupt 24 (hex). INT 24h is called by DOS when a 'critical error' occurs,
and it normally prints the familiar "Abort, Retry, Ignore?" message.
With the INT 24h handler installed, errors of this type will be passed on to
Turbo Pascal as an error. If I/O checking is on, this will cause a program
crash. If I/O checking is off, IOResult will return an error code. The
global variable INT24Err will be true if an INT 24h error has occurred. The
variable INT24ErrorCode will contain the INT 24h error code as given by DOS.
These errors can be found in the DOS Technical Reference Manual.
It is intended that INT24Result be used in place of IOResult. Calling
INT24Result clears IOResult. The simple way to use INT24Result is just to
check that it returns zero, and if not, handle all errors the same. The more
complicated way is to interpret the code. The integer returned by INT24Result
can be looked at as two bytes. By assigning INT24Result to a variable, you
can then examine the two bytes: (Hi(<variable>)-1) will give the DOS critical
error code, or (<variable> And $FF00) will return an integer from the table
listed in the INT24Result procedure (two ways of looking at the critical
error); Lo(<variable>) will give Turbo's IOResult. A critical error will
always be reflected in INT24Result, but the IOResult part of INT24Result will
not necessarily be nonzero; in particular, unsuccessful writes to character
devices will not register as a Turbo I/O error.
INT24Result should be called after any operation which might cause a
critical error, if Turbo's I/O checking is disabled. If it is enabled, the
program will be aborted except in the above noted case of writes to character
devices.
Also note that different versions of DOS and the BIOS seem to react to
printer errors at vastly different rates. Be prepared to wait a while for
anything to happen (in an error situation) on some machines.
These routines are known to work correctly with: Turbo Pascal 1.00B PC-DOS;
Turbo Pascal 2.00B PC-DOS;
Turbo Pascal 2.00B MS-DOS;
Turbo Pascal 3.01A PC-DOS.
Other MS-DOS and PC-DOS versions should work.
Note that Turbo 2.0's normal IOResult codes for MS-DOS DO NOT correspond to
the I/O error numbers given in Appendix I of the Turbo 2.0 manual, or to the
error codes given in the I/O error nn, PC=aaaa/Program aborted message. Turbo
3.0 IOResult codes do match the manual. Here is a table of the correspondence
(all numbers in hexadecimal):
Turbo 2.0 IOResult Turbo error, Turbo 3.0 IOResult
------------------ -------------------------------------------------
00 00 none
01 90 record length mismatch
02 01 file does not exist
03 F1 directory is full
04 FF file disappeared
05 02 file not open for input
06 03 file not open for output
07 99 unexpected end of file
08 F0 disk write error
09 10 error in numeric format
0A 99 unexpected end of file
0B F2 file size overflow
0C 99 unexpected end of file
0D F0 disk write error
0E 91 seek beyond end of file
0F 04 file not open
10 20 operation not allowed on a logical device
11 21 not allowed in direct mode
12 22 assign to standard files is not allowed
- Bela Lubkin
CompuServe 76703,3015
1/28/86
}
Procedure INT24;
Const FCBFuncs: Array [1..6] Of Byte=(14,15,21,22,27,28);
Begin
{ To understand this routine, you will need to read the description of
Interrupt 24h in the DOS manual. It also helps to examine and trace the
generated code under DEBUG. }
Inline($0E/$0E/$1F/$07/$C6/$06/ INT24Err /$01/$89/$EC/$83/$C4/$08/
$89/$F8/$A2/ INT24ErrCode /$58/$B9/$06/$00/$BF/ FCBFuncs /$F2/
$AE/$75/$04/$B0/$01/$EB/$08/$3C/$39/$B0/$FF/$72/$02/$B0/$83/
$5B/$59/$5A/$5E/$5F/$89/$E5/$80/$4E/$0A/$01/$5D/$1F/$07/$CF);
{ Turbo: PUSH BP (Save caller's stack frame
MOV BP,SP Set up this procedure's stack frame
PUSH BP ?)
Inline: PUSH CS
PUSH CS
POP DS Set DS and ES temporarily to CS
POP ES
MOV BYTE [INT24Err],1 Set INT24Err to True (CS:)
MOV SP,BP Get correct SP; ADD: Discard saved
ADD SP,8 BP, INT 24h return address & flags
MOV AX,DI Get INT 24h error code
MOV [INT24ErrCode],AL Save it in INT24ErrCode
POP AX Get initial DOS call number
MOV CX,6 Search for it in FCBFuncs: is this one
MOV DI,Offset FCBFuncs of the FCB functions that requires an
REPNZ SCASB error code of 01 in AL?
JNZ .1
MOV AL,1 Yes: set it
JMP .2
.1 CMP AL,39h No: is it an FCB function that requires
MOV AL,0FFh AL=FFh (function <39h)? Yes: set it.
JB .2
MOV AL,83h No: handle call, return error 83h, call
failed via INT 24h.
The error code (1, FFh or 83h) is
returned to the Turbo runtime routine
that called DOS, making it look like
a simple DOS error. Turbo handles
the I/O error.
.2 POP BX Pop the rest of the registers saved by
POP CX the initial INT 21h.
POP DX
POP SI
POP DI
MOV BP,SP
OR Byte Ptr [BP+0Ah],1 Set the carry flag in the saved Flags reg.
POP BP
POP DS
POP ES
IRET Return to next instruction: all regs.
restored, AL=error code, carry set. }
End;
Procedure INT24On; { Enable INT 24h trapping }
Begin
INT24Err:=False;
With RegisterSet Do
Begin
AX:=$3524;
MsDos(RegisterSet);
If (OldINT24[1] Or OldINT24[2])=0 Then
Begin
OldINT24[1]:=ES;
OldINT24[2]:=BX;
End;
DS:=CSeg;
DX:=Ofs(INT24);
AX:=$2524;
MsDos(RegisterSet);
End;
End;
Procedure INT24Off; { Disable INT 24h trapping. Should be done at the end of
the program, if you plan to run the program from within
the Turbo compiler. If the INT 24h handler is left in
place, and the compiler gets a critical error, the
system is likely to crash. }
Begin
INT24Err:=False;
If OldINT24[1]<>0 Then
With RegisterSet Do
Begin
DS:=OldINT24[1];
DX:=OldINT24[2];
AX:=$2524;
MsDos(RegisterSet);
End;
OldINT24[1]:=0;
OldINT24[2]:=0;
End;
Function INT24Result: Integer;
Var
I:Integer;
Begin
I:=IOResult;
If INT24Err Then
Begin
I:=I+256*Succ(INT24ErrCode);
INT24On;
End;
INT24Result:=I;
End;
{ INT24Result returns all the regular Turbo IOResult codes if no critical
error has occurred. If a critical error, then the following values are
added to the error code from Turbo:
256: Attempt to write on write protected disk
512: Unknown unit [internal dos error]
768: Drive not ready [drive door open or bad drive]
1024: Unknown command [internal dos error]
1280: Data error (CRC) [bad sector or drive]
1536: Bad request structure length [internal dos error]
1792: Seek error [bad disk or drive]
2048: Unknown media type [bad disk or drive]
2304: Sector not found [bad disk or drive]
2560: Printer out of paper [anything that the printer might signal]
2816: Write fault [character device not ready]
3072: Read fault [character device not ready]
3328: General failure [several meanings]
If you need the IOResult part, use
I:=INT24Result and 255; [masks out the INT 24h code]
For the INT 24h code, use
I:=INT24Result Shr 8; [same as Div 256, except faster]
INT24Result clears both error codes, so you must assign it to a variable if
you want to extract both codes:
J:=INT24Result;
WriteLn('Turbo IOResult = ',J And 255);
WriteLn('DOS INT 24h code = ',J Shr 8);
Note that in most cases, errors on character devices (LST and AUX) will not
return an IOResult, only an INT 24h error code. }